﻿using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace HQS.TokenInterpolation.Test
{
    [TestClass]
    public class TestSyntaxExceptions
    {
        [TestMethod]
        [ExpectedException(typeof (SyntaxException))]
        public void TemplateWithMultipleOpenings()
        {
            const string template = @"
{invoke:foreach this:{Orders} template:order}
@template ((name:order) 
{
  Order Name:   {order.Current.Name}
}
";
            try
            {
                Result result = Parser.Parse(template, CreateDataContext());
            }
            catch (SyntaxException se)
            {
                DisplayException(se);
                throw;
            }
        }

        [TestMethod]
        [ExpectedException(typeof (SyntaxException))]
        public void TemplateWithMultipleClosings()
        {
            const string template = @"
{invoke:foreach this:{Orders}  template:order}
@template (name:order) )
{
  Order Number: {order.Current.OrderNo} 
}
";
            DataSourcesVisitor context = CreateDataContext();
            try
            {
                Result result = Parser.Parse(template, CreateDataContext());
            }
            catch (SyntaxException se)
            {
                DisplayException(se);

                throw;
            }
        }

        [TestMethod]
        [ExpectedException(typeof (SyntaxException))]
        public void TemplateWithNoBody()
        {
            const string template = @"
Dear {Name}
Here are the items:
{invoke:foreach this:{Orders}  template:order}

@template (name:order) 
 Order Name:   {order.Current.Name}
  Order Number: {order.Current.OrderNo} 

";

            DataSourcesVisitor context = CreateDataContext();
            try
            {
                Result result = Parser.Parse(template, CreateDataContext());
            }
            catch (SyntaxException se)
            {
                DisplayException(se);

                throw;
            }
        }

        [TestMethod]
        [ExpectedException(typeof (SyntaxException))]
        public void TokenAssignedToTemplateNotFound()
        {
            const string template = @"
Dear {Name}
Here are the items:
{invoke:foreach this:{Orders}  template:order}

@template (namef:order) 
{
 Order Name:   {order.Current.Name}
  Order Number: {order.Current.OrderNo} 
}
";
            DataSourcesVisitor context = CreateDataContext();
            try
            {
                Result result = Parser.Parse(template, CreateDataContext());
            }
            catch (SyntaxException se)
            {
                DisplayException(se);

                throw;
            }
        }

        [TestMethod]
        [ExpectedException(typeof (SyntaxException))]
        public void TokenWithMultipleClosing()
        {
            const string template = "Dear {Name}}";
            DataSourcesVisitor context = CreateDataContext();
            try
            {
                Result result = Parser.Parse(template, CreateDataContext());
            }
            catch (SyntaxException se)
            {
                DisplayException(se);
                throw;
            }
        }

        [TestMethod]
        [ExpectedException(typeof (SyntaxException))]
        public void TokenWithAbondonedOpen()
        {
            const string template = "Dear { {Name}";
            DataSourcesVisitor context = CreateDataContext();
            try
            {
                Result result = Parser.Parse(template, CreateDataContext());
            }
            catch (SyntaxException se)
            {
                DisplayException(se);
                throw;
            }
        }

        private static DataSourcesVisitor CreateDataContext()
        {
            var context =
                new DataSourcesVisitor(
                    new
                    {
                        Name = "John",
                        Orders = new List<object> {new {OrderNo = 1, Name = "Phone"}, new {OrderNo = 2, Name = "Car"}}
                    });
            return context;
        }

        private void DisplayException(SyntaxException se)
        {
            Debug.WriteLine(se.OffendingText);
            Debug.WriteLine(se.ToString());
        }
    }
}